/*
 * RegistrarServlet.java
 *
 * Created on April 4th, 2007
 */
package clicktodial.sip;

import clicktodial.model.ModelFacade;
import clicktodial.model.Person;
import java.io.IOException;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.sip.Address;
import javax.servlet.sip.SipFactory;
import javax.servlet.sip.SipServlet;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import javax.servlet.sip.SipURI;
import javax.servlet.sip.URI;


/**
 * A servlet to handle SIP REGISTER requests.  This is a simple example that
 * does not perform any authentication.  It uses the requested SIP username
 * to map to a user in the database, and stores the user's contact URI in
 * the database for future use.
 *
 * @author jkaplan
 */
public class RegistrarServlet extends SipServlet {

    private static final Logger logger = 
            Logger.getLogger(RegistrarServlet.class.getName());
    
    // inject the SipFactory
    @Resource(mappedName="sip/ClickToDial")
    private SipFactory sf;
    
    /**
     * Handle a SIP Register request.  This relies on a few different
     * SIP headers to work: <ul>
     * <li><b>To</b> the SIP URI to be registered, which includes the
     * username in the user part of the SIP URI.
     * <li><b>Contact</b> the user's contact information, which contains the
     * actual URI to contact when we want to send invites to this user.
     * <li><b>Expires</b> the expiration time for this registration.  If
     * the expiration time is 0, then this is a request to unregister the
     * user.
     * </ul>
     * This sends a SIP response of either <code>OK</code> if the user is
     * found in the database or <code>NOT_FOUND</code> if the user is not
     * found in the database.
     */
    protected void doRegister(SipServletRequest req) 
        throws ServletException, IOException 
    {
        logger.info("Received register request: " + req.getTo());
        
        int response = SipServletResponse.SC_SERVER_INTERNAL_ERROR;
        ModelFacade mf = (ModelFacade) getServletContext().getAttribute("Model");
        
        // Figure out the name the user is registering with.  This is the
        // user portion of the SIP URI, e.g. "Bob" in "sip:Bob@x.y.z:port"
        String username = null;
        if (req.getTo().getURI().isSipURI()) {
            username = ((SipURI) req.getTo().getURI()).getUser();
        }
        
        // get the Person object from the database
        Person p = mf.getPerson(username);
        if (p != null) {
            // the Expires header tells us if this is a registration or
            // unregistration attempt.  An expires value of 0 or no Expires
            // header means it is an unregistration.
            int expires = 0;
            String expStr = req.getHeader("Expires");
            if (expStr != null) {
                expires = Integer.parseInt(expStr);
            }
            
            if (expires == 0) {
                // unregister
                response = handleUnregister(req, p);
            } else {
                // register
                response = handleRegister(req, p);
            }
        } else {
            // no person found in the database
            response = SipServletResponse.SC_NOT_FOUND;
        }
    
        // send the response
        SipServletResponse resp = req.createResponse(response);
        resp.send();
    }
    
    /**
     * Handle a registration request
     * @param req the request for registration
     * @param p the person in the database to register
     * @return the response to the register request
     */
    private int handleRegister(SipServletRequest req, Person p)
        throws ServletException
    {

        // Get the contact address from the request.  Prefer the
        // "Contact" address if given, otherwise use the "To" address
        Address addr = req.getTo();
        String contact = req.getHeader("Contact");
        if (contact != null) {
            addr = sf.createAddress(contact);
        }
        
        logger.info("Register address: " + addr);
        
        // store the contact address in the database
        p.setTelephone(addr.getURI().toString());
        
        ModelFacade mf = (ModelFacade) getServletContext().getAttribute("Model");
        mf.updatePerson(p);
        
        return SipServletResponse.SC_OK;
    }
    
    /**
     * Handle an unregistration request
     * @param req the request for unregistration
     * @param p the person in the database to unregister
     * @return the response to the unregister request
     */
    private int handleUnregister(SipServletRequest req, Person p) {
        // store the contact address in the database
        p.setTelephone(null);
        
        ModelFacade mf = (ModelFacade) getServletContext().getAttribute("Model");
        mf.updatePerson(p);
        
        return SipServletResponse.SC_OK;
    }
}
